package com.yd.mq.parse.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.google.common.base.Strings;
import com.yd.mq.parse.cache.AlarmActiveCacheUtils;
import com.yd.mq.parse.cache.AlarmCancelCacheUtils;
import com.yd.mq.parse.cache.AlarmDictionaryCacheUtils;
import com.yd.mq.parse.cache.SiteStationsCacheUtils;
import com.yd.mq.parse.model.AlarmDictionary;
import com.yd.mq.parse.model.AlarmRecord;
import com.yd.mq.parse.model.AlarmRecordTask;
import com.yd.mq.parse.model.ObservedAlarm;
import com.yd.mq.parse.model.SiteStations;
import com.yd.mq.parse.service.AlarmDictionaryService;
import com.yd.mq.parse.service.AlarmRecordService;
import com.yd.mq.parse.service.ObservedAlarmService;

import tk.mybatis.mapper.entity.Condition;

/**
 * 报文入库
 * 
 * @ClassName Alarm2DBService
 * @author ZuoLG
 * @date 2017年8月25日 下午3:29:23
 */
@Component
public class Alarm2DBService {

	/* 日志处理 */
	private Logger						log	= Logger.getLogger(this.getClass().getName());

	/* 时间处理 */
	private SimpleDateFormat			sdf	= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	/* 数据入库服务 */
	@Resource
	private AlarmRecordService			alarmRecordService;

	/* 数据入库服务 */
	@Resource
	private ObservedAlarmService		observedAlarmService;

	/* 数据服务 */
	@Resource
	private AlarmDictionaryService		dictionaryService;

	/* 过滤报文2g */
	@Value("${alarm.objectClass.2g}")
	private String						alarmObjectClass2g;

	/* 过滤报文4g */
	@Value("${alarm.objectClass.4g}")
	private String						alarmObjectClass4g;

	/* 多个激活告警的过期时间 */
	@Value("${alarm.overdueTime}")
	private int							overdueTime;

	/* 规则缓存 */
	@Autowired
	private AlarmDictionaryCacheUtils	dictionaryCacheUtils;

	/* 缓存 */
	@Autowired
	private SiteStationsCacheUtils		stationsCacheUtils;

	public void init(Map<String, String> map, File file) {

		try {
			alarmRecord(map, file);
		} catch (ParseException e) {
			e.printStackTrace();
			log.info("error.异常！" + e.getMessage());
		}
	}

	/*
	 * 执行入库初始化
	 */
	public void alarmRecord(Map<String, String> map, File file) throws ParseException {
		String path = file != null ? file.getAbsolutePath() : null;

		/** 数据过滤，如果对象为空则跳过过滤 **/
		// ObjectClass=201,300 属于2G数据，其他值统一都4G
		final String ObjectClass = map.get("ObjectClass");

		// 跳过空的和0
		boolean objFlag = Strings.isNullOrEmpty(ObjectClass) || ObjectClass.equals("0");
		if (objFlag) {
			log.info("跳过当前报文，报文ObjectClass:" + ObjectClass);
			return;
		}

		boolean aoc2g = !Strings.isNullOrEmpty(alarmObjectClass2g) && !alarmObjectClass2g.contains(ObjectClass);
		boolean aoc4g = !Strings.isNullOrEmpty(alarmObjectClass4g) && !alarmObjectClass4g.contains(ObjectClass);
		if (aoc2g && aoc4g) {
			log.info("报文ObjectClass:" + ObjectClass + ",不在2G解析范围:" + alarmObjectClass2g + ",4G范围:" + alarmObjectClass4g
					+ "内。");
			return;
		}

		log.info("开始报文解析......ObjectClass：" + ObjectClass);
		/******************************************************* 报文解析 ********************************************************/
		// OmcId
		final String omcId = map.get("OmcId");
		// ActiveStatus [0,1]-0：取消告警,1:激活告警
		final String ActiveStatus = map.get("ActiveStatus");
		// 查询获取AlarmRecord对象
		final String cFp0 = map.get("C_FP0");
		final String cFp1 = map.get("C_FP1");
		final String cFp2 = map.get("C_FP2");
		final String cFp3 = map.get("C_FP3");
		final String siteId = map.get("extra_string1");// 基站ID
		String baseName = map.get("ne_location");// 基站名称
		baseName = Strings.isNullOrEmpty(baseName) ? null : baseName;
		final String probableCauseTxt = map.get("ProbableCauseTxt");// 告警详情
		// 2G bscName 2G非空，4G为空
		final String bscName = map.get("eqp_label");
		final String alarmNo = map.get("ProbableCause");// 告警码
		final String manufacturer = omcId.substring(0, 1);// 厂家
		final String eventTime = map.get("EventTime");// 时间
		log.info("**** 当前处理消息时间 ：" + eventTime);
		final String msgSerialStr = map.get("MsgSerial");// 序列号
		final String alarmText = map.get("AlarmText");// 告警原始报文
		final String msgSerial = msgSerialStr.substring(msgSerialStr.indexOf("_") + 1, msgSerialStr.length());
		final Date date = sdf.parse(eventTime);// 告警事件产生时间
		String subInfo = null;// 诺基亚附加信息
		// 诺基亚需解析附加信息
		if (manufacturer.equals("4")) {
			subInfo = !aoc2g ? getSubInfo2G(alarmText) : (!aoc4g ? getSubInfo4G(alarmText) : null);
		}

		/******************************************************* 解析完成 ********************************************************/

		boolean isActive = true;// 是否激活告警true:激活告警，false：取消告警
		isActive = !(ActiveStatus != null && (ActiveStatus.equals("0") || Integer.parseInt(ActiveStatus) == 0));

		if (!isActive) {
			log.info("收到取消告警！" + path);
		}

		log.info("数据封装-ActiveStatus:" + ActiveStatus + ",omcId:" + omcId + ",siteId:" + siteId + ",baseName:" + baseName
				+ ",alarmNo:" + alarmNo + ",cFp0:" + cFp0 + ",cFp1:" + cFp1 + ",cFp2:" + cFp2 + ",cFp3:" + cFp3
				+ ",eventTime:" + eventTime);

		if (siteId == null || siteId.equals("0")) {
			log.info("站号为0或空的处理：,siteId:" + siteId + ",baseName:" + baseName + ",alarmNo:" + alarmNo + ",cFp0:" + cFp0
					+ ",cFp1:" + cFp1 + ",cFp2:" + cFp2 + ",cFp3:" + cFp3 + ",path:" + path);
			File reNameFile = new File(file.getAbsolutePath() + "_site");
			if (file.renameTo(reNameFile)) {
				log.info("站号为0或空的文件已经改名成功:" + reNameFile.getAbsolutePath());
			} else {
				log.info("站号为0或空的文件已经改名失败:" + reNameFile.getAbsolutePath());
			}
			return;
		}

		/******************************************************* 数据存储对象 ********************************************************/
		// 告警记录对象
		AlarmRecord record = new AlarmRecord();
		ObservedAlarm observedAlarm = null;

		/** 对象属性设置 **/
		record.setSiteId(siteId);// 基站ID
		record.setSiteName(baseName);// 基站名称
		if (bscName != null && !bscName.equals("")) {
			record.setBscName(bscName);// bscname
		}
		//TODO(亿阳在报文中添加sectorId后，将此处换成对应的sectorId名)
		record.setSectorId(map.get("extra_string1"));// 基站扇区ID（小区ID)
		// 亿阳生成的告警电子指纹
		record.setcFp0(cFp0);// C_FP0
		record.setcFp1(cFp1);// C_FP1
		record.setcFp2(cFp2);// C_FP2
		record.setcFp3(cFp3);// C_FP3
		record.setAlarmNo(alarmNo);// 告警码
		record.setAlarmName(probableCauseTxt);// 告警详情
		record.setManufacturerId(getManufacturer(manufacturer));// 生厂商ID
		record.setSubinfo(subInfo);

		// 查询是否存在当前告警的激活告警
		AlarmRecord selectRecord = alarmRecordService.selectAlarmRecord(record);

		log.info("selectRecord=" + selectRecord);

		// 设置observedAlarm的值,当前记录是取消告警，数据正常
		if (selectRecord != null && !isActive) {
			// observedAlarm = observedAlarmService.findBy("recordId",
			// selectRecord.getId());
			Condition condition = new Condition(ObservedAlarm.class);

			condition.createCriteria().andEqualTo("recordId", selectRecord.getId()).andIsNull("cancelTime");
			List<ObservedAlarm> list = observedAlarmService.findByCondition(condition);
			if (list.size() != 0) {
				observedAlarm = list.get(0);
			}
		} else {
			observedAlarm = new ObservedAlarm();
			// 计算程序
			observedAlarm.setSiteId(siteId);// 基站ID
			observedAlarm.setSectorId(record.getSectorId());//
			observedAlarm.setBscName(bscName);// 基站BSCNAME
			observedAlarm.setAlarmNo(alarmNo);// 告警码
			observedAlarm.setHourOfMonth(new Long(DateUtils.getCurrentHour()).intValue());

			// 设置基站信息,解析小区号SectorId后需加入小区号判断
			SiteStations stations = getSiteStations(siteId, bscName, record.getSectorId());
			if (stations != null) {
				observedAlarm.setSiteDictionaryId(stations.getId());
			}

		}

		/******************************************************* 告警时间处理 ********************************************************/
		// 0：取消告警
		if (!isActive) {
			record.setCancelReceivedTime(date);// 收到告警取消的时间(文件生成的时间)
			record.setAlarmCancelTime(date);// 告警取消时间
			record.setAlarmCancelSerial(msgSerial);// 告警取消序列号(亿阳生成)
			observedAlarm.setCancelTime(date);// 告警结束时间
		} else {// 激活告警
			record.setActiveReceivedTime(date);// 收到激活告警的时间(文件生成的时间)
			record.setAlarmActiveTime(date);// 告警激活时间
			record.setAlarmActiveSerial(msgSerial);// 告警激活序列号(亿阳生成)
			observedAlarm.setActiveTime(date);// 告警开始时间
		}

		/******************************************************* 优化机制 ********************************************************/
		/** 优化机制-同时多个激活告警处理部分 **/
		// 如果查询到已经有激活告警，并且当前记录也是激活告警,同时2个激活告警情况
		if (selectRecord != null && selectRecord.getAlarmCancelTime() == null && isActive) {
			log.info("当前记录库中已有记录，并且又收到一条激活告警!");
			overdueTime = overdueTime == 0 ? 30 : overdueTime;
			AlarmRecordTask alarmRecordTask = new AlarmRecordTask();
			// 当前时间加过期未收到取消告警时间
			// 创建 Calendar 对象
			Calendar calendar = Calendar.getInstance();
			alarmRecordTask.setRecordTime(calendar.getTime());
			// 30分钟之后过期
			calendar.add(Calendar.MINUTE, overdueTime);
			alarmRecordTask.setOverdueTime(calendar.getTime());
			alarmRecordTask.setAlarmRecord(selectRecord);
			alarmRecordTask.setCancelTime(selectRecord.getAlarmActiveTime());
			AlarmActiveCacheUtils.getInstance().list.add(alarmRecordTask);
		}

		/** 优化机制-取消时间缓存部分 **/
		// 1.如果record对象为空，并且是取消告警，设置取消告警等待
		// 2.每次激活告警都需到取消告警等待列表查找是否有对应的取消告警
		// 3.Key 规则Key_cFp0_cFp1_cFp2_cFp3
		final String key = "Key_" + siteId + "_" + alarmNo + "_" + cFp0 + "_" + cFp1 + "_" + cFp2 + "_" + cFp3;

		if (selectRecord == null && record != null && !isActive) {
			log.info("放入缓存数据key:" + key);
			AlarmCancelCacheUtils.addAlarmRecord(key, record);
		}

		// 存在数据,取出数据设置给当前对象，并移除
		AlarmRecord cacheRecord = AlarmCancelCacheUtils.getAlarmRecord(key);
		if (cacheRecord != null) {
			log.info("取出缓存数据key:" + key);
			record.setCancelReceivedTime(cacheRecord.getCancelReceivedTime());// 收到告警取消的时间(文件生成的时间)
			record.setAlarmCancelTime(cacheRecord.getAlarmCancelTime());// 告警取消时间
			record.setAlarmCancelSerial(cacheRecord.getAlarmCancelSerial());// 告警取消序列号(亿阳生成)
			observedAlarm.setCancelTime(cacheRecord.getAlarmCancelTime());// 告警结束时间
		}

		// 获取当前时间在当前月属于第n个小时

		/******************************************************* 字典数据处理部分 ********************************************************/
		AlarmDictionary dictionary = getAlarmDictionary(alarmNo);

		// 如果当前报文属于2g，并且bsc—name为空，则打印信息
		if (!Strings.isNullOrEmpty(alarmObjectClass2g)
				&& (alarmObjectClass2g.contains(ObjectClass) || ObjectClass.contains(alarmObjectClass2g))
				&& Strings.isNullOrEmpty(bscName)) {
			log.info("报文ObjectClass:" + ObjectClass + ",bscName为空" + bscName);
			if (dictionary != null) {
				observedAlarm.setFrequencyDictionaryId(dictionary.getGsmFrequencyDictionaryId());// 告警频次扣分标准
				observedAlarm.setLatencyDictionaryId(dictionary.getGsmLatencyDictionaryId());// 告警延时扣分标准
				observedAlarm.setAlarmNameCn(dictionary.getAlarmNameCn());// 告警中文名称
				observedAlarm.setAlarmDictionaryId(dictionary.getId());
			}
		} else {
			// 4G
			if (dictionary != null) {
				observedAlarm.setFrequencyDictionaryId(dictionary.getLteFrequencyDictionaryId());// 告警频次扣分标准
				observedAlarm.setLatencyDictionaryId(dictionary.getLteLatencyDictionaryId());// 告警延时扣分标准
				observedAlarm.setAlarmNameCn(dictionary.getAlarmNameCn());// 告警中文名称
				observedAlarm.setAlarmDictionaryId(dictionary.getId());
			}
		}

		/******************************************************* 数据入库部分 ********************************************************/
		log.info("开始入库......");
		try {
			if (isActive) {
				// 激活告警
				alarmRecordService.save(record);
				// 得到查询出来的ID
				observedAlarm.setRecordId(record.getId());
				if (dictionary == null || Strings.isNullOrEmpty(dictionary.getAlarmNo())) {
					log.info("未在AlarmDictionary中找到alarmNo:" + alarmNo + "的数据。");
				} else {
					observedAlarmService.save(observedAlarm);
				}

			} else {
				log.info("修改取消告警!");
				alarmRecordService.updateAlarmRecord(record);
				// 如果是新增的时候添加record无异常，则可直接获取ID
				// observedAlarm.setRecordId(record.getId());
				// 在字典中未找到记录，输出日志
				if (dictionary == null || Strings.isNullOrEmpty(dictionary.getAlarmNo())) {
					log.info("未在AlarmDictionary中找到alarmNo:" + alarmNo + "的数据。");
				} else {
					log.info("修改考核结果表!recordID :" + record.getId());
					observedAlarmService.update(observedAlarm);
				}
			}
		} catch (Exception e) {
			// e.printStackTrace();
			log.error("Error 数据入库异常!" + e.getMessage());
		}
		log.info("结果入库完成。");

	}

	/**
	 * 返回厂家信息 @return int @throws
	 */
	private Integer getManufacturer(String manufacturer) {
		// 报文信息,imcid,8:华为，9:大唐，7:中心，203:普天,4:诺西
		// 数据库对应：//诺基亚：0 华为：1 中兴：2 大唐：3 普天：4
		Integer manufacturerInt = null;
		if (manufacturer.equals("4")) {
			manufacturerInt = 0;
		}
		if (manufacturer.equals("8")) {
			manufacturerInt = 1;
		}
		if (manufacturer.equals("7")) {
			manufacturerInt = 2;
		}
		if (manufacturer.equals("9")) {
			manufacturerInt = 3;
		}
		if (manufacturer.equals("2")) {
			manufacturerInt = 4;
		}
		return manufacturerInt;
	}

	/**
	 * 获取附加信息，适用于nokia @return String @throws
	 */
	private static String getSubInfo2G(String alarmText) {
		// 前缀
		final String prefix = "User info";
		// 附加信息
		String subInfo = null;
		try {

			BufferedReader br = new BufferedReader(new InputStreamReader(
					new ByteArrayInputStream(alarmText.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
			String line;
			while ((line = br.readLine()) != null) {
				if (!line.trim().equals("")) {
					if (line.startsWith(prefix)) {
						subInfo = line;
					}
				}
			}
			subInfo = subInfo.replaceAll(prefix, "").toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return subInfo;
	}

	/**
	 * 获取4g @return String @throws
	 */
	private static String getSubInfo4G(String alarmText) {
		// 前缀
		final String prefix = "ALARM_TEXT";
		// 附加信息
		String subInfo = null;
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					new ByteArrayInputStream(alarmText.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
			String line;
			while ((line = br.readLine()) != null) {
				if (!line.trim().equals("")) {
					if (line.startsWith(prefix)) {
						subInfo = line;
					}
				}
			}
			if (!Strings.isNullOrEmpty(subInfo)) {
				if (subInfo.indexOf(";") > 0 && subInfo.length() > 2) {
					subInfo = subInfo.substring(subInfo.indexOf(";") + 1, subInfo.length()).trim();
				}
				if (subInfo.indexOf(";") > 0 && subInfo.length() > 2) {
					subInfo = subInfo.substring(subInfo.indexOf("||") + 2, subInfo.indexOf("||||")).trim();
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return subInfo;
	}

	/**
	 * 获取基站信息 @return SiteStations @throws
	 */
	private SiteStations getSiteStations(String site_id, String bsc_name, String sectorId) {
		List<SiteStations> list = stationsCacheUtils.getSiteStationsList();
		SiteStations stations = null;

		/** 2G拿到的 site_id 中包含字母，需要去除 */
		if (!Strings.isNullOrEmpty(bsc_name)) {
			Pattern sitePattern = Pattern.compile("\\d+");
			Matcher msp = sitePattern.matcher(site_id);
			try {
				if(msp.find()){
					String siteStr = msp.group();
					if (!Strings.isNullOrEmpty(siteStr)){
						site_id = Integer.valueOf(siteStr).toString();
					}
				}
			}catch (Exception e){
				log.info(" ****** 2G 转换基站ID异常 :" + e.getMessage());
			}
		}

		for (SiteStations ss : list) {
			if (!Strings.isNullOrEmpty(bsc_name)) {
				//TODO(从亿阳获取到sectorId后打开此处条件判断)
				// if (ss.getSiteId().equals(site_id) &&
				// ss.getBscName().equals(bsc_name)&&ss.getSectorId().equals(sectorId))
				// {
				if (ss.getSiteId().equals(site_id) && ss.getBscName().equals(bsc_name)) {
					stations = ss;
				}
			} else {
				if (ss.getSiteId().equals(site_id)) {
					stations = ss;
				}
			}
		}
		return stations;
	}

	/**
	 * 返回AlarmDictionary @return AlarmDictionary @throws
	 */
	private AlarmDictionary getAlarmDictionary(String alarmNo) {
		AlarmDictionary dictionary = null;
		List<AlarmDictionary> list = dictionaryCacheUtils.getAlarmDictionaryList();
		for (AlarmDictionary alarmDictionary : list) {
			if (alarmDictionary.getAlarmNo().equals(alarmNo)) {
				dictionary = alarmDictionary;
				break;
			}
		}
		return dictionary;
	}

}
